package blacklist

import (
	"database/sql"
	"fmt"

	"black_list_analyze/lib"
)

type List struct {
	Id         string
	TypeId     int            `db:"type_id"`
	AppId      string         `db:"app_id"`
	ExpireDate sql.NullString `db:"expire_date"`
	UpdateDate string         `db:"update_date"`
}

// check record is existed in current table
func IsExistedInBlackList(id string, typeId int, appId string) (bool, error) {
	flag, err := isExisted(id, typeId, appId, "list_black")
	return flag, lib.PackgeErr("IsExistedInBlackList", err)
}

func IsExistedInGrayList(id string, typeId int, appId string) (bool, error) {
	flag, err := isExisted(id, typeId, appId, "list_gray")
	return flag, lib.PackgeErr("IsExistedInGrayList", err)
}

func IsExistedInWhiteList(id string, typeId int, appId string) (bool, error) {
	flag, err := isExisted(id, typeId, appId, "list_white")
	return flag, lib.PackgeErr("IsExistedInWhiteList", err)
}

func isExisted(id string, typeId int, appId, table string) (bool, error) {
	var list []List
	query := fmt.Sprintf("select * from %s where id=? and type_id=? and app_id=?", table)
	err := conn.Select(&list, query, id, typeId, appId)
	if err != nil {
		return false, err
	}
	return len(list) != 0, nil
}

// insert or update list
func InsertOrUpdateBlackList(id string, typeId int, appId, expireDate string) (err error) {
	if expireDate == "" {
		err = insertOrUpdateListWithoutExpire(id, typeId, appId, "list_black")
	} else {
		err = insertOrUpdateList(id, typeId, appId, expireDate, "list_black")
	}
	return lib.PackgeErr("InsertOrUpdateBlackList", err)
}

func InsertOrUpdateGrayList(id string, typeId int, appId, expireDate string) (err error) {
	if expireDate == "" {
		err = insertOrUpdateListWithoutExpire(id, typeId, appId, "list_gray")
	} else {
		err = insertOrUpdateList(id, typeId, appId, expireDate, "list_gray")
	}
	return lib.PackgeErr("InsertOrUpdateGrayList", err)
}

func insertOrUpdateList(id string, typeId int, appId, expireDate, table string) (err error) {
	query := fmt.Sprintf(`
	INSERT INTO %s (id, type_id, app_id, expire_date)
	VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE update_date=CURRENT_TIMESTAMP(), expire_date=VALUES(expire_date)`, table)
	_, err = conn.Exec(query, id, typeId, appId, expireDate)
	return
}

func insertOrUpdateListWithoutExpire(id string, typeId int, appId, table string) (err error) {
	query := fmt.Sprintf(`
	INSERT INTO %s (id, type_id, app_id)
	VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE update_date=CURRENT_TIMESTAMP(), expire_date=NULL`, table)
	_, err = conn.Exec(query, id, typeId, appId)
	return
}

// delete list
func DeleteExpiredBlackList(expireDate string) error {
	return lib.PackgeErr("DeleteExpiredBlackList",
		deleteExpiredList(expireDate, "list_black"))
}

func DeleteExpiredGrayList(expireDate string) error {
	return lib.PackgeErr("DeleteExpiredGrayList",
		deleteExpiredList(expireDate, "list_gray"))
}

func DeleteExpiredWhiteList(expireDate string) error {
	return lib.PackgeErr("DeleteExpiredWhiteList",
		deleteExpiredList(expireDate, "list_white"))
}

func deleteExpiredList(expireDate string, table string) error {
	query := fmt.Sprintf("delete from %s where expire_date is not null and expire_date <= ?", table)
	_, err := conn.Exec(query, expireDate)
	return err
}
